﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp10
{


    public partial class Form1 : Form
    {
        public int my_border = 5;//边缘宽度
        Rectangle nameRec;
        string name = "变压器";
        Point nameLocation;
        Size nameSize;
        Label label;
        Font font = new Font("宋体", 14);
        bool mouseDown = false;
        Rectangle my_rect = new Rectangle(50, 50, 200, 100);
        Rectangle old_rect;
        public ResizeType m_type;
        public bool onResize = false;
        public Point dragPoint = Point.Empty;
        TextBox nameTextBox;

        public enum ResizeType
        {
            Left,
            Right,
            Top,
            Bottom,
            LeftTop,
            RightTop,
            LeftBottom,
            RightBottom,
        }

        public Form1()
        {
            InitializeComponent();
            //得到字体的像素值大小
            nameSize = TextRenderer.MeasureText(name, font);
            DoubleBuffered = true;
            nameRec = new Rectangle(my_rect.X + 10, my_rect.Y + 10, my_rect.Width - 20, my_rect.Height - 20);
            
            //labelInit();
        }
        //初始化矩形内的标签
        private void labelInit()
        {
            label = new Label();
            label.Text = "变压器";
            label.Font = font;
            label.Size = my_rect.Size;
            label.TextAlign = ContentAlignment.MiddleCenter;
            label.BackColor = Color.Transparent;
            label.BorderStyle = BorderStyle.None;
            label.Location = my_rect.Location;
            this.Controls.Add(label);
            
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(Pens.Red, my_rect);
            nameRec = new Rectangle(my_rect.X + 10, my_rect.Y + 10, my_rect.Width - 20, my_rect.Height - 20);
            e.Graphics.DrawRectangle(Pens.Green, nameRec);
            nameLocation = new Point(nameRec.X + nameRec.Width / 2 - nameSize.Width / 2, nameRec.Y + nameRec.Height / 2 - nameSize.Height / 2);
            e.Graphics.DrawString(name, font, new SolidBrush(Color.Red), nameLocation) ;
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            string str = string.Format("x={0}, Y={1}", e.Location.X, e.Location.Y);
            MouseToolTip.SetToolTip(this, str);
            //Cursor.Position 指的是屏幕坐标， PointToClient 可以转化为在客户端的坐标
            //Console.WriteLine(PointToClient(Cursor.Position));
            //如果是改变大小模式 则改变形状 此时不进行是否为边界判断
            if (onResize)
            {
                changeShape(e);
            }
            else
            {
                isBorder(my_rect, ref m_type);
            }
            //如果鼠标点击状态下 鼠标在长方形内部 则进行移动 并改变鼠标状态
            if (mouseDown && isInRect(my_rect, e) && nameTextBox == null)
            {
                moveRectangle(e); 
            }
            
            
            
        }

        public void moveRectangle(MouseEventArgs e)
        {
            //移动相对位置 需要旧矩形的坐标 否则移动时会一直刷新
            Point newPoint = new Point(old_rect.X + e.Location.X - dragPoint.X, old_rect.Y + e.Location.Y - dragPoint.Y);
            my_rect = new Rectangle(newPoint, my_rect.Size);   
            Refresh();
        }

        //改变形状
        public void changeShape(MouseEventArgs e) 
        {
            int diffY = dragPoint.Y - e.Location.Y;
            int diffX = dragPoint.X - e.Location.X;
            switch (m_type)
            {
                //加入条件 可以四面八方随意拖动
                case ResizeType.Left:
                    if (old_rect.Right > e.Location.X)
                    {
                        my_rect = new Rectangle(old_rect.Left - diffX, old_rect.Top, old_rect.Width + diffX, old_rect.Height);
                    }
                    else
                    {
                        my_rect = new Rectangle(old_rect.Right, old_rect.Top, Math.Abs(old_rect.Width + diffX), old_rect.Height);
                    }
                    break;
                case ResizeType.Right:
                    if (old_rect.Left < e.Location.X)
                    {
                        my_rect = new Rectangle(old_rect.Left, old_rect.Top, old_rect.Width - diffX, old_rect.Height);
                    }
                    else
                    {
                        my_rect = new Rectangle(e.Location.X, old_rect.Top, Math.Abs(old_rect.Width - diffX), old_rect.Height);
                    }
                    break;
                case ResizeType.Top:
                    if (old_rect.Bottom > e.Location.Y)
                    {
                        my_rect = new Rectangle(old_rect.Left, old_rect.Top - diffY, old_rect.Width, old_rect.Height + diffY);
                    }
                    else
                    {
                        my_rect = new Rectangle(old_rect.Left, old_rect.Bottom, old_rect.Width, Math.Abs(old_rect.Height + diffY));
                    }
                    break;
                case ResizeType.Bottom:
                    if (old_rect.Top < e.Location.Y)
                    {
                        my_rect = new Rectangle(old_rect.Left, old_rect.Top, old_rect.Width, old_rect.Height - diffY);
                    }
                    else
                    {
                        my_rect = new Rectangle(old_rect.Left, e.Location.Y, old_rect.Width, Math.Abs(old_rect.Height - diffY));
                    }
                    break;
                case ResizeType.RightTop:
                    if (old_rect.Left < e.Location.X && old_rect.Bottom > e.Location.Y)
                    {
                        my_rect = new Rectangle(old_rect.Left, old_rect.Top - diffY, old_rect.Width - diffX, old_rect.Height + diffY);
                    }
                    else
                    {
                        my_rect = new Rectangle(Math.Min(old_rect.Left, e.Location.X), Math.Min(old_rect.Top - diffY, old_rect.Bottom), Math.Abs(old_rect.Width - diffX), Math.Abs(old_rect.Height + diffY));

                    }
                    break;
                case ResizeType.LeftTop:
                    if (old_rect.Right > e.Location.X && old_rect.Bottom > e.Location.Y)
                    {
                        my_rect = new Rectangle(old_rect.Left - diffX, old_rect.Top - diffY, old_rect.Width + diffX, old_rect.Height + diffY);
                    }
                    else
                    {
                        my_rect = new Rectangle(Math.Min(old_rect.Left - diffX, old_rect.Right), Math.Min(old_rect.Top - diffY, old_rect.Bottom), Math.Abs(old_rect.Width + diffX), Math.Abs(old_rect.Height + diffY));
                    }
                    break;
                case ResizeType.LeftBottom:
                    if (old_rect.Top < e.Location.Y && old_rect.Right > e.Location.X)
                    {
                        my_rect = new Rectangle(old_rect.Left - diffX, old_rect.Top, old_rect.Width + diffX, old_rect.Height - diffY);
                    }
                    else
                    {
                        my_rect = new Rectangle(Math.Min(old_rect.Left - diffX, old_rect.Right), Math.Min(old_rect.Top, e.Location.Y), Math.Abs(old_rect.Width + diffX), Math.Abs(old_rect.Height - diffY));
                    }
                    break;
                case ResizeType.RightBottom:
                    if (old_rect.Left < e.Location.X && old_rect.Top < e.Location.Y)
                    {
                        my_rect = new Rectangle(old_rect.Left, old_rect.Top, old_rect.Width - diffX, old_rect.Height - diffY);
                    }
                    else
                    {
                        my_rect = new Rectangle(Math.Min(old_rect.Left, e.Location.X), Math.Min(old_rect.Top, e.Location.Y), Math.Abs(old_rect.Width - diffX), Math.Abs(old_rect.Height - diffY));
                    }
                    break;
                default:
                    Console.WriteLine(m_type.ToString());
                    break;

            }
            Invalidate();
        }

        public bool isInRect(Rectangle rect, MouseEventArgs e)
        {
            //包含在矩形内部 除去边界的范围内
            if (rect.Top + my_border < e.Location.Y && 
                rect.Bottom - my_border > e.Location.Y &&
                rect.Left + my_border < e.Location.X &&
                rect.Right - my_border > e.Location.X)
            {
                Cursor = Cursors.SizeAll;
                return true;
            }
            else
            {
                Cursor = Cursors.Default;
            }
            return false;
        }
        //判断 是否为矩形框边界
        public bool isBorder(Rectangle rect, ref ResizeType type)
        {
            Point cursorPoint = PointToClient(Cursor.Position);

            if (Math.Abs(cursorPoint.X - rect.Left) < my_border && Math.Abs(cursorPoint.Y - rect.Top) < my_border)
            {
                type = ResizeType.LeftTop;
                Cursor = Cursors.SizeNWSE;
            }
            else if (Math.Abs(cursorPoint.X - rect.Right) < my_border && Math.Abs(cursorPoint.Y - rect.Top) < my_border)
            {
                type = ResizeType.RightTop;
                Cursor = Cursors.SizeNESW;
            }
            else if (Math.Abs(cursorPoint.X - rect.Left) < my_border && Math.Abs(cursorPoint.Y - rect.Bottom) < my_border)
            {
                type = ResizeType.LeftBottom;
                Cursor = Cursors.SizeNESW;
            }
            else if (Math.Abs(cursorPoint.X - rect.Right) < my_border && Math.Abs(cursorPoint.Y - rect.Bottom) < my_border)
            {
                type = ResizeType.RightBottom;
                Cursor = Cursors.SizeNWSE;
            }
            else if (Math.Abs(cursorPoint.X - rect.Left) < my_border && cursorPoint.Y > rect.Top && cursorPoint.Y < rect.Bottom)
            {
                type = ResizeType.Left;
                Cursor = Cursors.SizeWE;
            }
            else if (Math.Abs(cursorPoint.X - rect.Right) < my_border && cursorPoint.Y > rect.Top && cursorPoint.Y < rect.Bottom)
            {
                type = ResizeType.Right;
                Cursor = Cursors.SizeWE;
            }
            else if (Math.Abs(cursorPoint.Y - rect.Bottom) < my_border && cursorPoint.X > rect.Left && cursorPoint.X < rect.Right)
            {
                type = ResizeType.Bottom;
                Cursor = Cursors.SizeNS;
            }
            else if (Math.Abs(cursorPoint.Y - rect.Top) < my_border && cursorPoint.X > rect.Left && cursorPoint.X < rect.Right)
            {
                type = ResizeType.Top;
                Cursor = Cursors.SizeNS;
            }
            else
            {
                Cursor = Cursors.Default;
                return false;
            }
            return true;

        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                mouseDown = true;
                old_rect = my_rect;
                dragPoint = e.Location;
                if (isBorder(my_rect, ref m_type))
                {
                    onResize = true;
                }
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                onResize = false;
                mouseDown = false;
                dragPoint = Point.Empty;
            }        
        }

        private void Form1_DoubleClick(object sender, EventArgs e)
        {
            if (isInRect(nameRec, (MouseEventArgs)e))
            {
                //在方框内部双击 编辑文字
                nameTextBox = new TextBox();
                nameTextBox.Font = font;
                nameTextBox.Location = nameLocation;
                nameTextBox.Size = nameSize;
                nameTextBox.BorderStyle = BorderStyle.None;
                nameTextBox.Text = name;
                this.Controls.Add(nameTextBox);
                nameTextBox.Focus();
            }
            else { 
                if(nameTextBox != null)
                {
                    name = nameTextBox.Text;
                    nameSize = TextRenderer.MeasureText(name, font);
                    nameTextBox.Hide();
                    nameTextBox = null;
                    Invalidate();
                }
            }
        }
    }
}
